
/*
 * primary source用于实现向主循环中异步增加source
 */

#include "tp_typedef.h"
#include "tp_globals.h"
#include "tp_event.h"
#include "tp_memory.h"
#include "tp_pipe.h"
#include "tp_source_primary.h"

typedef struct _PrivInfo
{
	TpPipe* pipe;
	TpOnEvent on_event;
	void* user_data;
}PrivInfo;

static int tp_source_primary_get(TpSource* thiz)
{
	DECL_PRIV(thiz, priv);

	if (NULL == priv)
	{
		return -1;
	}

	return tp_pipe_get_read_fd(priv->pipe);
}

static int tp_source_primary_check(TpSource* thiz)
{
	return -1;
}

static void tp_source_primary_destroy(TpSource* thiz)
{
	if (NULL != thiz)
	{
		DECL_PRIV(thiz, priv);

		if (NULL != priv)
		{
			tp_pipe_destroy(priv->pipe);
		}

		tp_free(thiz);
	}

	return;
}

static TpRet tp_source_primary_dispatch(TpSource* thiz)
{
	TpEvent event = {0};

	if(NULL != thiz)
	{
		DECL_PRIV(thiz, priv);
		if(NULL == priv || tp_pipe_read(priv->pipe, &event, sizeof(event)) == sizeof(event))
		{
			return TP_RET_FAIL;
		}

        priv->on_event(priv->user_data, &event);
	}

	return TP_RET_OK;
}

TpSource* tp_source_primary_create(TpOnEvent on_event, void* user_data)
{
	TpSource* thiz = NULL;
	thiz = (TpSource*)tp_alloc(sizeof(TpSource) + sizeof(PrivInfo));
	if (NULL != thiz)
	{
		DECL_PRIV(thiz, priv);

		priv->pipe = tp_pipe_create();
		if (NULL == priv->pipe)
		{
			tp_free(thiz);
			thiz = NULL;
		}
		else
		{
			priv->on_event = on_event;
			priv->user_data = user_data;

			thiz->get = tp_source_primary_get;
			thiz->check = tp_source_primary_check;
			thiz->dispatch = tp_source_primary_dispatch;
			thiz->destroy = tp_source_primary_destroy;
		}
	}

	return thiz;
}

TpRet tp_primary_source_queue_event(TpSource* thiz, TpEvent* event)
{
    DECL_PRIV(thiz, priv);

    if(NULL == thiz || NULL == event)
    {
        return TP_RET_BADARGS;
    }

    if(NULL == priv) return TP_RET_FAIL;

    return tp_pipe_write(priv->pipe, event, sizeof(TpEvent));
}